home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / Tickle-4.0 (tcl) / tcl / expecTerm / alarm.c next >
Encoding:
C/C++ Source or Header  |  1993-11-17  |  5.6 KB  |  219 lines  |  [TEXT/MPS ]

  1. /* alarm.c
  2. ***************************************************************************** 
  3. expecTerm version 1.0 beta
  4. Mark Weissman
  5. Christopher Matheus
  6. Copyright 1992 by GTE Laboratories Incorporated.
  7.  
  8. Portions of this work are in the public domain.  Permission to use,
  9. copy, modify, and distribute this software and its documentation for
  10. any purpose and without fee is hereby granted, provided that the above
  11. copyright notice appear in all copies and that both the copyright
  12. notice and warranty disclaimer appear in supporting documentation, and
  13. that the names of GTE Laboratories or any of their entities not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.
  16.  
  17. GTE disclaims all warranties with regard to this software, including
  18. all implied warranties of merchantability and fitness for a particular
  19. purpose, even if GTE Laboratories Incorporated knows about the
  20. purpose.  In no event shall GTE be liable for any special, indirect or
  21. consequential damages or any damages whatsoever resulting from loss of
  22. use, data or profits, whether in an action of contract, negligence or
  23. other tortuous action, arising out of or in connection with the use or
  24. performance of this software.
  25.  
  26. This code is based on and may include parts of Don Libes' expect code:
  27.   expect written by: Don Libes, NIST, 2/6/90
  28.   Design and implementation of expect was paid for by U.S. tax
  29.   dollars.  Therefore it is public domain.  However, the author and NIST
  30.   would appreciate credit if this program or parts of it are used.
  31. ******************************************************************************/
  32.  
  33. #include <stdio.h>
  34. #include <setjmp.h>
  35. #include <signal.h>
  36. #include <sys/time.h>    /* for time(3) */
  37. #include <tcl.h>
  38. #include "compat.h"
  39. #include "translate.h"
  40. #include "global.h"
  41. static jmp_buf env;    /* for interruptable read() */
  42. static int env_valid = FALSE;    /* whether we can longjmp or not */
  43. typedef void (*VFPTR)();
  44. VFPTR Signal();
  45.  
  46. struct timeval *AddTimeval(t1,t2) 
  47. struct timeval *t1, *t2;
  48. {
  49.   t1->tv_sec  += t2->tv_sec;
  50.   t1->tv_usec += t2->tv_usec;
  51.   if (t1->tv_usec >= uS_PER_SEC) {
  52.     t1->tv_usec -= uS_PER_SEC;
  53.     t1->tv_sec += 1;
  54.   }
  55.   return(t1);
  56. }
  57.  
  58. struct timeval *SubtractTimeval(t1,t2) 
  59. struct timeval *t1, *t2;
  60. {
  61.   if (t1->tv_usec < t2->tv_usec) {
  62.     if (t1->tv_sec < 1) t2 = t1;
  63.     else {
  64.       t1->tv_usec += uS_PER_SEC;
  65.       t1->tv_sec -= 1;
  66.     }
  67.   }
  68.   if (t1->tv_sec < t2->tv_sec) t2 = t1;
  69.   t1->tv_sec  -= t2->tv_sec;
  70.   t1->tv_usec -= t2->tv_usec;
  71.   return(t1);
  72. }
  73.  
  74. struct timeval *DoubleToTimeval(t, tv)
  75. double t;
  76. struct timeval *tv;
  77. {
  78.   static struct timeval tv_struct;
  79.   if (!tv) tv = &tv_struct;
  80.  
  81.   tv->tv_sec =  (unsigned) t;
  82.   tv->tv_usec = (unsigned) ((double)uS_PER_SEC * (t - tv->tv_sec));
  83.   return(tv);
  84. }
  85.  
  86. double TimevalToDouble(tv)
  87. struct timeval *tv;
  88. {
  89.   if (!tv) return(100000.0);
  90.   else return((double)tv->tv_sec + ((double)tv->tv_usec)/(double)uS_PER_SEC);
  91. }
  92.  
  93. double TimeOfDay() {
  94.   struct timeval tv;
  95.   gettimeofday(&tv,NULL);
  96.   return((double)tv.tv_sec + ((double)tv.tv_usec)/(double)uS_PER_SEC);
  97. }
  98.  
  99. /*ARGSUSED*/
  100. void
  101. sigalarm_handler(n)
  102. int n;                   /* unused, for compatibility with STDC */
  103. {
  104. #ifdef REARM_SIG
  105.     Signal(SIGALRM,sigalarm_handler);
  106. #endif
  107.  
  108.     /* check env_valid first to protect us from the alarm occurring */
  109.     /* in the window between i_read and alarm(0) */
  110.     if (env_valid) longjmp(env,1);
  111. }
  112.  
  113. /* upon interrupt, act like timeout */
  114. /*ARGSUSED*/
  115. void
  116. sigint_handler(n)
  117. int n;            /* unused, for compatibility with STDC */
  118. {
  119. #ifdef REARM_SIG
  120.     Signal(SIGINT,sigint_handler);/* not nec. for BSD, but doesn't hurt */
  121. #endif
  122.  
  123.     /* longjmp if we are executing a read inside of expect command */
  124.     if (env_valid) longjmp(env,1);
  125.  
  126.     /* if anywhere else in code, prepare to exit */
  127.     bye(0);
  128. }
  129.  
  130. VoidFuncArray init_expect_alarms(sigfuncs, flags)
  131. unsigned flags;
  132. void (*sigfuncs[])();
  133. {
  134.   static void (*isigfuncs[32])();
  135.   extern char *signal_to_string();
  136.   int n;
  137.   if (!sigfuncs) sigfuncs = isigfuncs;
  138.   for (n=0; n<32; ++n) {
  139.     if (flags & (1<<n)) {
  140.       debuglog("signal(%s:%d, %s)\n", signal_to_string(n), n, (n==SIGINT)?"sigint_handler":"sigalarm_handler");
  141.       if (n==SIGINT)   
  142.     sigfuncs[n]=Signal(n,sigint_handler);
  143.       else 
  144.     sigfuncs[n]=Signal(n,sigalarm_handler);
  145.     }
  146.     else sigfuncs[n]=NULL;
  147.   }
  148.   return(sigfuncs);
  149. }
  150.  
  151.  
  152.  
  153. Ualarm(value, interval)
  154. unsigned value, interval;
  155. {
  156.   struct itimerval it;
  157.   it.it_value.tv_sec  = value / uS_PER_SEC;
  158.   it.it_value.tv_usec = value % uS_PER_SEC;
  159.   it.it_interval.tv_sec  = interval / uS_PER_SEC;
  160.   it.it_interval.tv_usec = interval % uS_PER_SEC;
  161.   setitimer(ITIMER_REAL, &it, NULL);
  162. }
  163.  
  164. SetAlarm(wakeup)
  165. double wakeup;
  166. {
  167.   if (setjmp(env) != 1) {
  168.     env_valid = TRUE;
  169.     if (wakeup != -1.0) {
  170.       unsigned t = (unsigned)(wakeup*(double)uS_PER_SEC);
  171.       ualarm(t,0);
  172.     }
  173.     return(1);
  174.   }
  175.   else return(0);
  176. }
  177.  
  178. ClearAlarm()
  179. {
  180.   alarm(0);
  181.   env_valid = FALSE;
  182. }
  183.  
  184. AlarmReturn(val)
  185. int val;
  186. {
  187.   if (env_valid) longjmp(env,val);
  188.   else return(0);
  189. }
  190.  
  191. VFPTR Signal(sig, func)
  192. int sig;
  193. void (*func)();
  194. {
  195. #ifdef _AIX
  196.   struct sigaction action, oaction;
  197.   action.sa_flags = SA_RESTART & ~SA_ONSTACK & ~SA_OLDSTYLE & ~SA_NOCLDSTOP;
  198.   action.sa_mask.losigs = 0;
  199.   action.sa_mask.hisigs = 0;
  200.   action.sa_handler = func;
  201.   if (sigaction(sig, &action, &oaction) == 0) /* success */
  202.     return(oaction.sa_handler);
  203.   else return((VFPTR)-1);
  204. #else
  205. #ifdef _HP
  206.   return(signal(sig, func));
  207. #else
  208.   struct sigvec vec, ovec;
  209.   vec.sv_flags = ~SV_ONSTACK & ~SV_INTERRUPT & ~SV_RESETHAND;
  210.   vec.sv_mask = 1<<sig;
  211.   vec.sv_handler = func;
  212.   if (sigvec(sig, &vec, &ovec) == 0) /* success */
  213.     return(ovec.sv_handler);
  214.   else return((VFPTR)-1);
  215. #endif
  216. #endif
  217. }
  218.  
  219.